commonlibsse_ng\re\h/
hkArray.rs

1//! # hkArray
2//!
3//! This module defines the `hkArray` struct, a dynamic array-like structure that
4//! mimics the behavior of a C++ container with methods for array manipulation,
5//! including dynamic resizing, accessors, and iterators.
6mod array_base;
7
8use core::ops::{Index, IndexMut};
9
10pub use self::array_base::{
11    hkArrayBase, hkArrayDrain, hkArrayIterMut, hkArrayIterator, hkArrayRefIterator,
12};
13use crate::re::MemoryManager::TESGlobalAlloc;
14use std_fork::alloc::SelflessAllocator;
15
16/// A dynamic array container C++'s `hkArray`, backed by a custom allocator.
17///
18/// # Example
19/// ```
20/// use commonlibsse_ng::re::hkArray::hkArray;
21///
22/// let mut array = hkArray::<i32>::new();
23/// array.push(1);
24/// array.push(2);
25/// assert_eq!(array.len(), 2);
26/// assert_eq!(array[0], 1);
27/// ```
28///
29/// Note: The default allocator (`SkyrimAllocator`) only works in-game.
30/// For examples outside of the game, use `RustAllocator`.
31#[repr(C)]
32#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
33pub struct hkArray<T, A: SelflessAllocator = TESGlobalAlloc> {
34    __base: hkArrayBase<T, A>,
35}
36
37impl<T, A> hkArray<T, A>
38where
39    A: SelflessAllocator,
40{
41    /// Creates a new empty array.
42    ///
43    /// # Example
44    /// ```
45    /// use commonlibsse_ng::re::hkArray::hkArray;
46    ///
47    /// let array: hkArray<u32> = hkArray::new();
48    /// assert!(array.is_empty());
49    /// ```
50    #[inline]
51    pub const fn new() -> Self {
52        Self { __base: hkArrayBase::new() }
53    }
54
55    #[inline]
56    pub fn with_capacity(capacity: i32) -> Self {
57        Self { __base: hkArrayBase::with_capacity(capacity) }
58    }
59
60    /// Returns the number of elements in the array.
61    ///
62    /// # Example
63    /// ```
64    /// use commonlibsse_ng::re::hkArray::hkArray;
65    ///
66    /// let array = hkArray::<u32>::new();
67    /// assert_eq!(array.len(), 0);
68    /// ```
69    #[inline]
70    pub const fn len(&self) -> usize {
71        self.__base.len()
72    }
73
74    /// Returns the capacity of the array.
75    ///
76    /// # Example
77    /// ```
78    /// use commonlibsse_ng::re::hkArray::hkArray;
79    ///
80    /// let array = hkArray::<u32>::new();
81    /// assert_eq!(array.capacity(), 0);
82    /// ```
83    #[inline]
84    pub const fn capacity(&self) -> i32 {
85        self.__base.capacity()
86    }
87
88    /// Checks if the array is empty.
89    ///
90    /// # Example
91    /// ```
92    /// use commonlibsse_ng::re::hkArray::hkArray;
93    ///
94    /// let array = hkArray::<u32>::new();
95    /// assert!(array.is_empty());
96    /// ```
97    #[inline]
98    pub const fn is_empty(&self) -> bool {
99        self.__base.is_empty()
100    }
101
102    /// Reserves capacity for at least `new_capacity` elements.
103    ///
104    /// # Panics
105    /// Panics if `new_capacity` exceeds the internal capacity limit.
106    ///
107    /// # Example
108    /// ```
109    /// use commonlibsse_ng::re::hkArray::hkArray;
110    ///
111    /// let mut array = hkArray::<u32>::new();
112    /// array.reserve(10);
113    /// assert!(array.capacity() >= 10);
114    /// ```
115    #[inline]
116    pub fn reserve(&mut self, new_capacity: i32) {
117        self.__base.reserve(new_capacity);
118    }
119
120    /// Pushes a new element to the end of the array.
121    ///
122    /// # Panics
123    /// Panics if memory allocation fails.
124    ///
125    /// # Example
126    /// ```
127    /// use commonlibsse_ng::re::hkArray::hkArray;
128    ///
129    /// let mut array = hkArray::<u32>::new();
130    /// array.push(42);
131    /// ```
132    #[inline]
133    pub fn push(&mut self, value: T) {
134        self.__base.push(value);
135    }
136
137    /// Removes the last element from the array and returns it, or `None` if it's empty.
138    ///
139    /// # Example
140    /// ```
141    /// use commonlibsse_ng::re::hkArray::hkArray;
142    ///
143    /// let mut array = hkArray::<i32>::new();
144    /// array.push(1);
145    /// assert_eq!(array.pop(), Some(1));
146    /// assert_eq!(array.pop(), None);
147    /// ```
148    #[inline]
149    pub const fn pop(&mut self) -> Option<T> {
150        self.__base.pop()
151    }
152
153    /// Returns a reference to the element at the given index, if it exists.
154    ///
155    /// # Example
156    /// ```
157    /// use commonlibsse_ng::re::hkArray::hkArray;
158    ///
159    /// let mut array = hkArray::<i32>::new();
160    /// array.push(42);
161    /// assert_eq!(array.get(0), Some(&42));
162    /// assert_eq!(array.get(1), None);
163    /// ```
164    #[inline]
165    pub const fn get(&self, index: usize) -> Option<&T> {
166        self.__base.get(index)
167    }
168
169    /// Returns a mutable reference to the element at the given index, if it exists.
170    ///
171    /// # Example
172    /// ```
173    /// use commonlibsse_ng::re::hkArray::hkArray;
174    ///
175    /// let mut array = hkArray::<i32>::new();
176    /// array.push(10);
177    /// if let Some(x) = array.get_mut(0) {
178    ///     *x += 1;
179    /// }
180    /// assert_eq!(array[0], 11);
181    /// ```
182    #[inline]
183    pub const fn get_mut(&mut self, index: usize) -> Option<&mut T> {
184        self.__base.get_mut(index)
185    }
186
187    /// Clears the array, removing all elements but preserving the capacity.
188    ///
189    /// # Examples
190    /// ```
191    /// use commonlibsse_ng::re::BSTArray::{BSTArray};
192    ///
193    /// let mut array = BSTArray::<i32>::with_capacity(10);
194    /// array.push(1);
195    /// array.push(2);
196    /// assert_eq!(array.len(), 2);
197    /// array.clear();
198    /// assert_eq!(array.len(), 0);
199    /// assert_eq!(array.capacity(), 10); // Capacity is preserved
200    /// ```
201    #[inline]
202    pub fn clear(&mut self) {
203        self.__base.clear();
204    }
205
206    /// Checks if the array contains the given element.
207    ///
208    /// Returns `true` if the element is present in the array, and `false` otherwise.
209    ///
210    /// # Examples
211    ///
212    /// ```
213    /// use commonlibsse_ng::re::hkArray::hkArray;
214    ///
215    /// let mut array = hkArray::<i32>::with_capacity(10);
216    /// array.push(1);
217    /// array.push(2);
218    /// assert!(array.contains(&1));
219    /// assert!(!array.contains(&3));
220    /// ```
221    #[inline]
222    pub fn contains(&self, value: &T) -> bool
223    where
224        T: PartialEq,
225    {
226        for i in 0..self.len() {
227            if let Some(item) = self.get(i) {
228                if item == value {
229                    return true;
230                }
231            }
232        }
233        false
234    }
235
236    /// Retains only the elements that satisfy the predicate.
237    ///
238    /// This method takes a closure that accepts an element of the array and returns a boolean.
239    /// Elements for which the closure returns `true` will be kept, while elements for which
240    /// it returns `false` will be removed.
241    ///
242    /// # Examples
243    ///
244    /// ```
245    /// use commonlibsse_ng::re::hkArray::hkArray;
246    ///
247    /// let mut array = hkArray::<i32>::with_capacity(10);
248    /// array.push(1);
249    /// array.push(2);
250    /// array.push(3);
251    /// array.retain(|&x| x > 1);
252    /// assert_eq!(array.len(), 2);
253    /// assert!(array.contains(&2));
254    /// assert!(array.contains(&3));
255    /// ```
256    #[inline]
257    pub fn retain<F>(&mut self, f: F)
258    where
259        F: FnMut(&T) -> bool,
260    {
261        self.__base.retain(f);
262    }
263
264    /// Removes a range of elements from the array, returning them as a vector.
265    ///
266    /// This method removes the elements within the specified range and returns them as
267    /// a `Vec<T>`. The range must be within the bounds of the array.
268    ///
269    /// # Examples
270    ///
271    /// ```
272    /// use commonlibsse_ng::re::hkArray::hkArray;
273    ///
274    /// let mut array = hkArray::<i32>::with_capacity(10);
275    /// array.push(1);
276    /// array.push(2);
277    /// array.push(3);
278    /// array.push(4);
279    /// array.push(5);
280    /// let drained = array.drain(0..2);
281    /// assert_eq!(drained.collect::<Vec<_>>(), vec![1, 2]);
282    /// assert_eq!(array.len(), 3);
283    /// assert_eq!(array[0], 3);
284    /// assert_eq!(array[1], 4);
285    /// assert_eq!(array[2], 5);
286    /// ```
287    ///
288    /// # Panics
289    /// Panics if the range is out of bounds.
290    #[inline]
291    pub fn drain<R>(&mut self, range: R) -> hkArrayDrain<'_, T, A>
292    where
293        R: core::ops::RangeBounds<usize>,
294    {
295        self.__base.drain(range)
296    }
297
298    /// Return iterator
299    #[inline]
300    pub const fn iter(&self) -> hkArrayRefIterator<'_, T, A> {
301        self.__base.iter()
302    }
303
304    /// Return readonly slice.
305    #[inline]
306    pub const fn as_slice(&self) -> &[T] {
307        self.__base.as_slice()
308    }
309
310    /// Return mutable slice.
311    #[inline]
312    pub const fn as_mut_slice(&mut self) -> &mut [T] {
313        self.__base.as_mut_slice()
314    }
315}
316
317impl<T, A> hkArray<T, A>
318where
319    T: Clone,
320    A: SelflessAllocator,
321{
322    /// Resizes the array to the specified length, filling new elements with the given value.
323    ///
324    /// # Panics
325    /// Panics if `count` is negative or exceeds the maximum allowed capacity.
326    ///
327    /// # Example
328    /// ```
329    /// use commonlibsse_ng::re::hkArray::hkArray;
330    ///
331    /// let mut array = hkArray::<u32>::new();
332    /// array.resize(3, 7);
333    /// assert_eq!(array.len(), 3);
334    /// assert_eq!(array[0], 7);
335    /// ```
336    #[inline]
337    pub fn resize(&mut self, count: i32, value: T) {
338        self.__base.resize(count, value);
339    }
340}
341
342impl<T, A> Default for hkArray<T, A>
343where
344    A: SelflessAllocator,
345{
346    #[inline]
347    fn default() -> Self {
348        Self::new()
349    }
350}
351
352impl<T, A> IntoIterator for hkArray<T, A>
353where
354    A: SelflessAllocator,
355{
356    type Item = T;
357    type IntoIter = hkArrayIterator<T, A>;
358
359    #[inline]
360    fn into_iter(self) -> Self::IntoIter {
361        self.__base.into_iter()
362    }
363}
364
365impl<T, A> Index<usize> for hkArray<T, A>
366where
367    A: SelflessAllocator,
368{
369    type Output = T;
370
371    #[inline]
372    fn index(&self, index: usize) -> &Self::Output {
373        &self.__base[index]
374    }
375}
376
377impl<T, A> IndexMut<usize> for hkArray<T, A>
378where
379    A: SelflessAllocator,
380{
381    #[inline]
382    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
383        &mut self.__base[index]
384    }
385}
386
387#[cfg(test)]
388mod tests {
389    use stdx::alloc::Global;
390
391    use super::{hkArray as hkArray_, *};
392
393    type hkArray<T> = hkArray_<T, Global>;
394
395    #[test]
396    fn test_hk_array_new() {
397        let array: hkArray<i32> = hkArray::new();
398        assert_eq!(array.len(), 0);
399        assert!(array.is_empty());
400    }
401
402    #[test]
403    fn test_hk_array_push_back() {
404        let mut array = hkArray::new();
405        array.push(10);
406        array.push(20);
407
408        assert_eq!(array.len(), 2);
409        assert!(!array.is_empty());
410        assert_eq!(array.index(0), &10);
411        assert_eq!(array.index(1), &20);
412    }
413
414    #[test]
415    fn test_hk_array_resize_smaller() {
416        let mut array = hkArray::new();
417        array.push(10);
418        array.push(20);
419        array.push(30);
420
421        array.resize(2, 0);
422        assert_eq!(array.len(), 2);
423        assert_eq!(array.index(0), &10);
424        assert_eq!(array.index(1), &20);
425    }
426
427    #[test]
428    fn test_hk_array_resize_larger() {
429        let mut array = hkArray::new();
430        array.push(10);
431        array.push(20);
432
433        array.resize(5, 0);
434        assert_eq!(array.len(), 5);
435        assert_eq!(array.index(0), &10);
436        assert_eq!(array.index(1), &20);
437    }
438
439    #[test]
440    fn test_hk_array_into_iterator() {
441        let mut array = hkArray::new();
442        array.push(10);
443        array.push(20);
444
445        let mut iter = array.into_iter();
446        assert_eq!(iter.next(), Some(10));
447        assert_eq!(iter.next(), Some(20));
448        assert_eq!(iter.next(), None); // No more elements
449    }
450
451    #[test]
452    fn test_hk_array_reserve() {
453        let mut array = hkArray::new();
454        array.push(10);
455        array.push(20);
456
457        // Reserve more capacity
458        let initial_capacity = array.capacity();
459        array.reserve(10);
460        assert!(array.capacity() >= initial_capacity);
461    }
462
463    #[test]
464    fn test_hk_array_capacity() {
465        let mut array = hkArray::new();
466        assert_eq!(array.capacity(), 0); // Initially, capacity should be 0 or some small value
467
468        array.push(10);
469        assert!(array.capacity() > 0);
470    }
471}